package org.zhoulingbo.raft;

import java.util.List;

/**
 * raft协议节点
 */
public class RaftNode implements Constants {

    /**
     * 当前节点名称
     */
    String name;

    /**
     * 所有节点名称列表
     */
    List<RaftNode> nodeNameList;

    /**
     * 状态
     */
    int state = follower;

    /**
     * 计时器超时时间,单位ms
     */
    long timeout;

    /**
     * 选举轮次
     */
    volatile int term = 0;

    /**
     * 选举节点
     */
    volatile String voteNode = null;

    /**
     * 选举计数，超过半数则成为leader
     */
    volatile int voteCount = 0;

    Object object = new Object();

    long heartbeatTimeout = 100;

    MonitorThead monitorThead;

    int n = 0;

    public RaftNode(String name) {
        this.name = name;
        init();
        this.monitorThead = new MonitorThead(this);
    }

    public void setNodeNameList(List<RaftNode> nodeNameList) {
        this.nodeNameList = nodeNameList;
    }

    void init() {
        resetTimer();
    }

    /**
     * 重置计时器
     */
    void resetTimer() {
        this.timeout = (long) (150 + 150 * Math.random());
    }

    /**
     * 发送选举请求
     * @param voteTerm
     * @param voteFor
     * @return
     */
    String sendVoteRequest(int voteTerm, String voteFor) {
        boolean success = false;
        for (RaftNode raftNode : nodeNameList) {
            if (raftNode.name.equals(voteFor)) {
                continue;
            }
            boolean b = raftNode.handleVoteRequest(voteTerm, voteFor);
            if (b) {
                this.voteCount ++;
                if (this.voteCount >= this.nodeNameList.size()/2 + 1) {
                    success = true;
                    break;
                }
            }
        }

        if (success) {
            this.state = leader;
            System.out.println("节点" + this.name + "成为leader...");
            sendHeartbeat();
        } else {
            this.voteCount = 0;
            System.out.println("节点" + this.name + "选举失败...");
            monitorThead.interrupt();
        }

        return null;
    }

    void sendHeartbeat() {
        for (RaftNode raftNode : nodeNameList) {
            if (raftNode.name.equals(this.name)) {
                continue;
            }
            raftNode.handleHeartbeat();
        }
    }

    void handleHeartbeat() {
        this.resetTimer();
        monitorThead.interrupt();
    }

    /**
     * 处理选举请求, 同意返回true, 否则false
     * @param voteTerm
     * @return
     */
    boolean handleVoteRequest(int voteTerm, String voteFor) {
        if (voteTerm > this.term) {
            this.voteNode = voteFor;
            this.term = voteTerm;
            monitorThead.interrupt();
            return true;
        }

        if (voteTerm == this.term) {
            if (this.voteNode == null) {
                this.voteNode = voteFor;
                monitorThead.interrupt();
                return true;
            } else {
                monitorThead.interrupt();
                return false;
            }
        }
        monitorThead.interrupt();
        return false;
    }

    void vote() {
        this.term ++;
        this.voteNode = this.name;
        this.voteCount ++;
        if (this.voteCount >= this.nodeNameList.size()/2 + 1) {
            this.state = leader;
            System.out.println("节点" + this.name + "成为leader...!!!");
            return;
        }
        sendVoteRequest(this.term, this.voteNode);
    }

    public void start() {
        this.monitorThead.start();
    }

    public void destroy() {
        monitorThead.update();
    }

    class MonitorThead extends Thread {
        private RaftNode raftNode;
        public volatile boolean isExit = false;
        public MonitorThead(RaftNode raftNode) {
            this.raftNode = raftNode;
        }

        public void update() {
            isExit = true;
        }

        @Override
        public void run() {
            while (!isExit) {
                try {
                    if (raftNode.state == leader) {
                        sleep(raftNode.heartbeatTimeout);
                        sendHeartbeat();
                        raftNode.n ++;
                        System.out.println("节点" + raftNode.name + "发送心跳包...");
                        if (n >= 3) {
                            raftNode.destroy();
                        }
                    } else {
                        System.out.println("节点" + raftNode.name + "计时器开始计时..." + raftNode.timeout);
                        final long time = raftNode.timeout;
                        sleep(time);
                        System.out.println("节点" + raftNode.name + "计时器重置...");
                        if (raftNode.state == follower) {
                            System.out.println("节点" + raftNode.name + "成为candidate...");
                            raftNode.state = candidate;
                            raftNode.vote();
                        }
                        raftNode.resetTimer();
                    }
                } catch (InterruptedException e) {
                    System.out.println("节点" + raftNode.name + "被interrupted...");
                }
            }
        }
    }
}